package com.borball.store.comp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Timestamp;
import java.util.List;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableRowSorter;

import com.borball.store.dao.CardDAO;
import com.borball.store.dao.CustomerDAO;
import com.borball.store.dao.CustomerMoneyDAO;
import com.borball.store.dao.PStoreLogDAO;
import com.borball.store.dao.ProductReturnDAO;
import com.borball.store.dao.ProductStoreDAO;
import com.borball.store.domain.Card;
import com.borball.store.domain.Customer;
import com.borball.store.domain.CustomerMoney;
import com.borball.store.domain.MoneyBack;
import com.borball.store.domain.PStoreLog;
import com.borball.store.domain.ProductReturn;
import com.borball.store.domain.ProductStore;
import com.borball.store.domain.User;
import com.borball.store.util.StoreChangeActions;
import com.borball.store.util.UserUtils;

import craky.component.CommonTableModel;
import craky.componentc.JCButton;
import craky.componentc.JCComboBox;
import craky.componentc.JCLabel;
import craky.componentc.JCMessageBox;
import craky.componentc.JCNumberField;
import craky.componentc.JCPopupMenu;
import craky.componentc.JCScrollTable;
import craky.componentc.JCScrollText;
import craky.componentc.JCTable;
import craky.componentc.JCTableHeader;
import craky.keeper.EmptyComponent;
import craky.keeper.KeeperApp;
import craky.keeper.KeeperPane;
import craky.layout.LineLayout;

public class ReturnPane extends KeeperPane {

	private static final long serialVersionUID = 2583431180094797757L;

	private static final String CMD_INSERT = "Insert";

	private static final String CMD_MODIFY = "Modify";

	private static final String[] COLUMNS_NAME = { "流水", "时间", "客户", "产品", "数量", "金额", "经手人", "操作员", "备注" };

	protected KeeperApp keeper;
	protected User currentUser;
	protected CommonTableModel<ProductReturn> model;
	protected List<ProductReturn> data;
	protected ProductReturn currentData;
	protected Action insertAction, modifyAction, deleteAction, submitAction, cancelAction;
	protected JCTable table;
	protected JCPopupMenu popup;
	protected JComponent top, bottom, center;
	protected JComponent ecCustomer, ecProduct, ecAmount, ecMoney, ecUser, ecMemo;
	protected JCComboBox cpCustomer, cpProduct, cpUser;
	protected JCNumberField cpMoney, cpAmount;
	protected JCScrollText cpMemo;

	private JCButton btnModify, btnDelete, btnInsert, btnSubmit, btnCancel;
	private boolean modifying;
	private int selectedIndex;
	
	private CustomerDAO customerDAO = new CustomerDAO();
	private ProductReturnDAO productReturnDAO = new ProductReturnDAO();
	private CustomerMoneyDAO customerMoneyDAO = new CustomerMoneyDAO();
	private ProductStoreDAO productStoreDAO = new ProductStoreDAO();
	private PStoreLogDAO pStoreLogDAO = new PStoreLogDAO();
	private CardDAO cardDAO = new CardDAO();
	
	public ReturnPane(KeeperApp keeper) {
		this.keeper = keeper;
		this.currentUser = keeper.getCurrentUser();

		this.selectedIndex = -1;

		load();
		initActions();
		initUI();
		loadCustomer();
		loadUser();
		loadProduct();
	}

	private void loadCustomer() {
		List<Customer> customers = customerDAO.findAll();
	
		cpCustomer.removeAllItems();
		for (Customer c : customers) {
			cpCustomer.addItem(c.getName());
		}
		cpCustomer.setSelectedIndex(-1);
	}
	
	private void loadProduct() {
		List<Card> cards = cardDAO.findAll();
	
		cpProduct.removeAllItems();
		for (Card c : cards) {
			cpProduct.addItem(c.getName());
		}
		cpProduct.setSelectedIndex(-1);
	}
	

	private void loadUser() {
		List<User> users = UserUtils.getInstance().getAllUsers();
		
		cpUser.removeAllItems();
		for (User user : users) {
			cpUser.addItem(user.getName());
		}
		cpUser.setSelectedItem(keeper.getCurrentUser());
		
	}

	private void initActions() {
		insertAction = new AbstractAction("\u6DFB\u52A0") {
			private static final long serialVersionUID = 5056698643009336063L;

			public void actionPerformed(ActionEvent e) {
				insertOrModify(true);
			}
		};

		modifyAction = new AbstractAction("\u4FEE\u6539") {
			private static final long serialVersionUID = 8222836515926767063L;

			public void actionPerformed(ActionEvent e) {
				insertOrModify(false);
			}
		};

		deleteAction = new AbstractAction("\u5220\u9664") {
			private static final long serialVersionUID = -4608405524916997614L;

			public void actionPerformed(ActionEvent e) {
				delete();
			}
		};

		submitAction = new AbstractAction("\u786E\u5B9A") {
			private static final long serialVersionUID = 6989199497316998154L;

			public void actionPerformed(ActionEvent e) {
				submit();
			}
		};

		cancelAction = new AbstractAction("\u53D6\u6D88") {
			private static final long serialVersionUID = 6989199497316998154L;

			public void actionPerformed(ActionEvent e) {
				cancel();
			}
		};

		modifyAction.setEnabled(false);
		deleteAction.setEnabled(false);
	}

	private void initUI() {
		btnModify = new JCButton(modifyAction);
		btnDelete = new JCButton(deleteAction);
		btnInsert = new JCButton(insertAction);
		btnSubmit = new JCButton(submitAction);
		btnCancel = new JCButton(cancelAction);
		btnModify.setPreferredSize(new Dimension(-1, 21));
		btnDelete.setPreferredSize(btnModify.getPreferredSize());
		btnInsert.setPreferredSize(btnModify.getPreferredSize());
		btnSubmit.setPreferredSize(btnModify.getPreferredSize());
		btnCancel.setPreferredSize(btnModify.getPreferredSize());
		btnSubmit.setVisible(false);
		btnCancel.setVisible(false);
		EmptyComponent centerParent = new EmptyComponent();
		setLayout(new BorderLayout());
		centerParent.setLayout(new BorderLayout(0, 3));
		createCenter();
		createBottom();

		this.add(centerParent, BorderLayout.CENTER);

		if (center != null) {
			centerParent.add(center, BorderLayout.CENTER);
		}

		if (top != null) {
			centerParent.add(top, BorderLayout.NORTH);
		}

		if (bottom != null) {
			centerParent.add(bottom, BorderLayout.SOUTH);
		}

	}

	public void load() {
		data = productReturnDAO.findAll();
	}
	
	public void reload(){
		load();
		model.refreshUI();
	}

	protected JComponent createBottom() {

		bottom = new EmptyComponent();
		bottom.setBorder(new CompoundBorder(new EmptyBorder(0, 0, 0, 0), new LineBorder(new Color(84, 165, 213))));
		bottom.setPreferredSize(new Dimension(-1, 77));
		bottom.setLayout(new BorderLayout());
		bottom.add(createDetailComponent(), BorderLayout.CENTER);

		EmptyComponent buttonContainer = new EmptyComponent();
		buttonContainer.setLayout(new LineLayout(3, 0, 5, 0, 3, LineLayout.TRAILING, LineLayout.TRAILING,
				LineLayout.VERTICAL));
		buttonContainer.setPreferredSize(new Dimension(85, -1));
		buttonContainer.add(btnSubmit, LineLayout.END_FILL);

		buttonContainer.add(btnDelete, LineLayout.END_FILL);
		buttonContainer.add(btnModify, LineLayout.END_FILL);

		buttonContainer.add(btnInsert, LineLayout.END_FILL);
		buttonContainer.add(btnCancel, LineLayout.END_FILL);
		bottom.add(buttonContainer, BorderLayout.EAST);

		return bottom;
	}

	protected JComponent createCenter() {
		final Class<?>[] columnsClass = { Integer.class,  Timestamp.class, String.class,
				String.class, Integer.class, Float.class,
				String.class, String.class, String.class };
		final String[] getMethodsName = { "getId", "getCreated", "getCustomer", "getProduct",
				"getAmount", "getMoney",  "getUser",
				"getOperator", "getMemo" };
		final String[] setMethodsName = { "setId", "setCreated", "setCustomer", "setProduct",
				"setAmount", "setMoney", "setUser",
				"setOperator", "setMemo"  };
		final int[] columnsPreferredWidth = { 10, 40, 45, 10, 20, 60, 30, 30, 120};
		EmptyComponent ec = new EmptyComponent();
		JCScrollTable scTable = new JCScrollTable();
		table = scTable.getTable();
		model = new CommonTableModel<ProductReturn>(table, COLUMNS_NAME, columnsClass, getMethodsName, setMethodsName, data);
		TableRowSorter<CommonTableModel<ProductReturn>> sorter = new TableRowSorter<CommonTableModel<ProductReturn>>(model);

		scTable.setAlpha(0.0f);
		scTable.setColumnControlEnabled(false);
		ec.setLayout(new BorderLayout());
		ec.add(scTable, BorderLayout.CENTER);
		table.setModel(model);
		table.setDragEnabled(false);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setRowSorter(sorter);
		table.setRendererOpaque(false);
		((JCTableHeader) table.getTableHeader()).setShowPopupMenu(false);
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				whenSelectionChanged(e);
			}
		});
		table.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				select(e);
			}

			public void mouseReleased(MouseEvent e) {
				showPopupMenu(e);
			}
		});

		for (int i = 0; i < columnsPreferredWidth.length; i++) {
			table.getColumnModel().getColumn(i).setPreferredWidth(columnsPreferredWidth[i]);
		}

		return center = ec;
	}

	private JComponent createDetailComponent() {
		EmptyComponent ec = new EmptyComponent();
		EmptyComponent firstRow = new EmptyComponent();

		JCLabel lbCustomer = new JCLabel("客户");
		JCLabel lbProduct = new JCLabel("产品");
		JCLabel lbAmount = new JCLabel("数量");
		JCLabel lbUser = new JCLabel("经手人");
		JCLabel lbMemo = new JCLabel("备注");
		JCLabel lbMoney = new JCLabel("金额");
		
		Border border = new EmptyBorder(0, 0, 0, 5);
		cpCustomer = new JCComboBox();
		cpProduct = new JCComboBox();
		cpUser = new JCComboBox();
		cpMoney = new JCNumberField(0, 0, 999999);
		cpAmount = new JCNumberField(0, 0, 999);
		cpMemo = new JCScrollText();
		
		firstRow.setLayout(new BoxLayout(firstRow, BoxLayout.X_AXIS));
		firstRow.setPreferredSize(new Dimension(-1, 25));

		firstRow.add(ecCustomer = createTitledComponent(lbCustomer, cpCustomer, border, 3));
		firstRow.add(ecProduct = createTitledComponent(lbProduct, cpProduct, border, 3));
		firstRow.add(ecAmount = createTitledComponent(lbAmount, cpAmount, border, 3));
		firstRow.add(ecMoney = createTitledComponent(lbMoney, cpMoney, border, 3));
		firstRow.add(ecUser = createTitledComponent(lbUser, cpUser, border, 3));
		firstRow.add(ecMemo = createTitledComponent(lbMemo, cpMemo, border, 3));
		
		ec.setLayout(new BorderLayout(0, 5));
		ec.setBorder(new EmptyBorder(3, 5, 2, 2));
		ec.add(firstRow, BorderLayout.NORTH);

		ecCustomer.setPreferredSize(new Dimension(100, -1));
		ecProduct.setPreferredSize(new Dimension(100, -1));
		ecAmount.setPreferredSize(new Dimension(40, -1));
		ecMoney.setPreferredSize(new Dimension(35, -1));
		ecUser.setPreferredSize(new Dimension(40, -1));
		ecMemo.setPreferredSize(new Dimension(250, -1));
		
		resetTextStatus(false);
		
		return ec;
	}

	private JComponent createTitledComponent(JComponent titleComponent, JComponent component, Border border, int hgap) {
		EmptyComponent ec = new EmptyComponent();
		ec.setBorder(border);
		ec.setLayout(new BorderLayout(hgap, 0));
		ec.add(component, BorderLayout.CENTER);

		if (titleComponent != null) {
			ec.add(titleComponent, BorderLayout.WEST);
		}

		return ec;
	}

	private void resetDetailValues() {
		if (bottom.isVisible()) {
			if (currentData == null) {
				clearValues();
			} else {
				fillValues();
			}

			resetTextStatus(false);
			resetButtonStatus(false);
		}
	}

	private void clearValues() {
		cpCustomer.setSelectedIndex(-1);
		cpProduct.setSelectedIndex(-1);
//		cpUser.setSelectedIndex(-1);
		cpMoney.setText(null);
		cpAmount.setText(null);
		cpMemo.getEditor().setText(null);
	}

	private void fillValues() {
		cpCustomer.setSelectedItem(currentData.getCustomer());
		cpProduct.setSelectedItem(currentData.getProduct());
		cpUser.setSelectedItem(currentData.getUser());
		cpMoney.setText(String.valueOf((int)currentData.getMoney()));
		cpAmount.setText(String.valueOf((int)currentData.getAmount()));
		cpMemo.getEditor().setText(currentData.getMemo());

	}

	private void resetTextStatus(boolean editable) {
		cpCustomer.setEnabled(editable);
		cpProduct.setEnabled(editable);
		cpUser.setEnabled(editable);
		cpMoney.setEditable(editable);
		cpAmount.setEditable(editable);
		cpMemo.setEditable(editable);
	}

	private void resetButtonStatus(boolean modifying) {
		this.modifying = modifying;
		btnSubmit.setVisible(modifying);
		btnCancel.setVisible(modifying);
		btnInsert.setVisible(!modifying);
		btnModify.setVisible(!modifying);
		btnDelete.setVisible(!modifying);
	}

	private void select(MouseEvent e) {
		int row = table.rowAtPoint(e.getPoint());

		if (row >= 0 && SwingUtilities.isRightMouseButton(e)) {
			table.getSelectionModel().setSelectionInterval(row, row);
		} else if (row < 0 && !SwingUtilities.isMiddleMouseButton(e)) {
			if (selectedIndex >= 0) {
				table.clearSelection();
			} else {
				resetDetailValues();
			}
		}
	}

	private void showPopupMenu(MouseEvent e) {
		if (popup != null && SwingUtilities.isRightMouseButton(e)) {
			popup.show((Component) e.getSource(), e.getX(), e.getY());
		}
	}

	private void whenSelectionChanged(ListSelectionEvent e) {
		currentData = table.getSelectedRow() < 0 ? null : model.getSelectedRowData();
		boolean selectedEmpty = (selectedIndex = table.getSelectedRow()) < 0;
		modifyAction.setEnabled(!selectedEmpty);
		deleteAction.setEnabled(!selectedEmpty);
		resetDetailValues();
	}

	protected void resetRowValues(ProductReturn productReturn) {
		productReturn.setCustomer(cpCustomer.getSelectedItem().toString());
		productReturn.setProduct(cpProduct.getSelectedItem().toString());
		productReturn.setUser(cpUser.getSelectedItem().toString());
		productReturn.setMoney(Float.valueOf(cpMoney.getText()));
		productReturn.setAmount(Integer.valueOf(cpAmount.getText()));
		productReturn.setMemo(cpMemo.getEditor().getText());
	}

	public void cancel() {
		btnSubmit.setActionCommand(null);
		resetDetailValues();
	}

	protected boolean checkInput() {
		return true;
	}

	protected boolean checkFilter(User data) {
		return true;
	}

	public void submit() {
		if (!btnSubmit.isVisible() || !checkInput()) {
			return;
		}

		String cmd = btnSubmit.getActionCommand();
		boolean insert = true;
		ProductReturn pReturn = null;
		if (checkNull(insert)) {
			if (CMD_INSERT.equals(cmd)) {
				pReturn = new ProductReturn();
				pReturn.setCustomer(cpCustomer.getSelectedItem().toString().trim());
				pReturn.setUser(cpUser.getSelectedItem().toString().trim());
				pReturn.setMoney(Float.valueOf(cpMoney.getText()));
				pReturn.setAmount(Integer.valueOf(cpAmount.getText()));
				pReturn.setMemo(cpMemo.getEditor().getText().trim());
				pReturn.setCreated(new Timestamp(System.currentTimeMillis()));
				pReturn.setOperator(currentUser.getName());
				pReturn.setProduct(cpProduct.getSelectedItem().toString());
			} else if (CMD_MODIFY.equals(cmd)) {
				pReturn = currentData;
				insert = false;
			}

			resetRowValues(pReturn);

			if (insert) {
				productReturnDAO.add(pReturn);

				//update store
				updateStore(pReturn);
				//update money
				
//				updateCustomerMoney(m, true);
				
				model.insertRowData(pReturn);
				int row = model.convertRowIndexesToView(model.getRowCount() - 1)[0];
				table.getSelectionModel().setSelectionInterval(row, row);
			} else {
				productReturnDAO.update(pReturn);

//				updateCustomerMoney(m, false);

				model.refreshRowOnView(selectedIndex);
				fillValues();
			}
			resetButtonStatus(false);
			resetTextStatus(false);
			btnSubmit.setActionCommand(null);
		}
	}

	private void updateStore(ProductReturn pReturn) {
		List<ProductStore> all = productStoreDAO.findAll();
		Random rand =new Random();
		ProductStore store = all.get(rand.nextInt(all.size() -1));
		store.setAmount(store.getAmount() + pReturn.getAmount());
		store.setModified(new Timestamp(System.currentTimeMillis()));
		productStoreDAO.updateStore(store);
		
		PStoreLog log = new PStoreLog();
		log.setAction(StoreChangeActions.PRODUCTRETURN.getMessage());
		log.setAmount(pReturn.getAmount());
		log.setUser(pReturn.getUser());
		log.setPid(pReturn.getProduct());
		log.setCreated(new Timestamp(System.currentTimeMillis()));
		log.setMemo(pReturn.getMemo());
		log.setOutId(pReturn.getId());
		log.setOperator(pReturn.getOperator());
		pStoreLogDAO.add(log);		
	}

	private void updateCustomerMoney(MoneyBack m, boolean insert) {
		CustomerMoney cm = customerMoneyDAO.findByPK(m.getCustomer());
		boolean existing = true;
		if(cm == null){
			cm = new CustomerMoney();
			existing = false;
		}
			
		cm.setCustomer(m.getCustomer());
		cm.setReturnmoney(cm.getReturnmoney() + m.getMoney());
		cm.setModified(new Timestamp(System.currentTimeMillis()));
		
		if(insert)
			cm.setMemo(cm.getMemo() == null ? "" : cm.getMemo() + "|" + m.getId());
		
		if(existing)
			customerMoneyDAO.update(cm);
		else 
			customerMoneyDAO.add(cm);
	}

	private boolean checkNull(boolean insert) {
		if (cpCustomer.getSelectedIndex() < 0 || cpProduct.getSelectedIndex() < 0 || cpUser.getSelectedIndex() < 0
				|| "".equals(cpAmount.getText().trim()) || "".equals(cpMoney.getText().trim())) {

			JCMessageBox.createErrorMessageBox(keeper.getMainFrame(), "必填项为空", "请输入所有必填项").open();

			cpCustomer.requestFocus();
			return false;
		}
		return true;
	}

	public void insertOrModify(boolean insert) {
		if (modifying) {
			cancel();
		}

		btnSubmit.setActionCommand(insert ? CMD_INSERT : CMD_MODIFY);
		resetTextStatus(true);
		resetButtonStatus(true);

		if (insert) {
			clearValues();
			cpCustomer.requestFocus();
		}
	}

	public void delete() {
		String message = "\u786E\u5B9A\u8981\u5220\u9664\u8BE5\u8BB0\u5F55\u5417\uFF1F";
		JCMessageBox box = JCMessageBox.createQuestionMessageBox(keeper.getMainFrame(), "\u5220\u9664", message);

		if (box.open() == JCMessageBox.YES_OPTION) {
			productReturnDAO.delete(currentData);
			model.delRowOnViewAt(selectedIndex);
		}
	}

	public List<ProductReturn> getAllData() {
		return data;
	}

	@Override
	public String getType() {
		return "退货管理";
	};


	@Override
	public void refresh() {
		load();
		loadCustomer();
		loadUser();
		loadProduct();
		this.center.repaint();
	}
}
